<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/dute_favicon_32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/dute_favicon_16x16.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">
  <link rel="manifest" href="/images/manifest.json">
  <meta name="msapplication-config" content="/images/browserconfig.xml">
  <meta http-equiv="Cache-Control" content="no-transform">
  <meta http-equiv="Cache-Control" content="no-siteapp">
  <meta name="google-site-verification" content="mpI5dkydstZXl6UcDCppqktXK0bbvqdZ6LkZ3KNk4Iw">
  <meta name="baidu-site-verification" content="code-a1LksZX2Ds">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/gh/fancyapps/fancybox@3/dist/jquery.fancybox.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"whitestore.top","root":"/","scheme":"Gemini","version":"7.8.0","exturl":true,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":true,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":true,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="零拷贝">
<meta property="og:type" content="article">
<meta property="og:title" content="【Linux】Linux Zero-Copy Using sendfile">
<meta property="og:url" content="https://whitestore.top/2023/09/13/zerocopy/index.html">
<meta property="og:site_name" content="爱看书的阿东">
<meta property="og:description" content="零拷贝">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://adong-picture.oss-cn-shenzhen.aliyuncs.com/adong/20230825130421.png">
<meta property="article:published_time" content="2023-09-13T06:08:23.000Z">
<meta property="article:modified_time" content="2023-10-21T14:26:31.032Z">
<meta property="article:author" content="阿东">
<meta property="article:tag" content="linux">
<meta property="article:tag" content="zerocopy">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://adong-picture.oss-cn-shenzhen.aliyuncs.com/adong/20230825130421.png">

<link rel="canonical" href="https://whitestore.top/2023/09/13/zerocopy/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>【Linux】Linux Zero-Copy Using sendfile | 爱看书的阿东</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="爱看书的阿东" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">爱看书的阿东</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">赐他一块白色石头，石头上写着新名</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档</a>

  </li>
        <li class="menu-item menu-item-sitemap">

    <a href="/sitemap.xml" rel="section"><i class="fa fa-fw fa-sitemap"></i>站点地图</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    

  <span class="exturl github-corner" data-url="aHR0cHM6Ly9naXRodWIuY29tL2xhenlUaW1lcw==" title="Follow me on GitHub" aria-label="Follow me on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></span>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://whitestore.top/2023/09/13/zerocopy/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="阿东">
      <meta itemprop="description" content="随遇而安">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="爱看书的阿东">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          【Linux】Linux Zero-Copy Using sendfile
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2023-09-13 14:08:23" itemprop="dateCreated datePublished" datetime="2023-09-13T14:08:23+08:00">2023-09-13</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-10-21 22:26:31" itemprop="dateModified" datetime="2023-10-21T22:26:31+08:00">2023-10-21</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Linux/" itemprop="url" rel="index"><span itemprop="name">Linux</span></a>
                </span>
            </span>

          
            <span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display: none;">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span id="busuanzi_value_page_pv"></span>
            </span>
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="fa fa-comment-o"></i>
      </span>
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/2023/09/13/zerocopy/#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/2023/09/13/zerocopy/" itemprop="commentCount"></span>
    </a>
  </span>
  
  <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>5.8k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="fa fa-clock-o"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>5 分钟</span>
            </span>
            <div class="post-description">零拷贝</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="Source"><a href="#Source" class="headerlink" title="Source"></a>Source</h1><p>Source：<span class="exturl" data-url="aHR0cHM6Ly9tZWRpdW0uY29tL3N3bGgvbGludXgtemVyby1jb3B5LXVzaW5nLXNlbmRmaWxlLTc1ZDJlYjU2YjM5Yg==" title="https://medium.com/swlh/linux-zero-copy-using-sendfile-75d2eb56b39b">Linux Zero-Copy Using sendfile(). sendfile() has been gradually becoming… | by CocCoc Techblog | The Startup | Medium<i class="fa fa-external-link"></i></span></p>
<h1 id="Why-Zero-copy"><a href="#Why-Zero-copy" class="headerlink" title="Why Zero-copy?"></a>Why Zero-copy?</h1><p>What’s happening under the hood when the OS is copying a file / transfering a file to another host? </p>
<p>当操作系统将文件复制/传输到另一台主机时，在系统底层下发生了什么？</p>
<p>For our naked eyes the process can be simple, OS first reads content of the file, then writes it to another file, then it’s done! </p>
<p>我们<strong>肉眼</strong>看到的过程可能很简单：<strong>操作系统首先读取文件内容，然后将其写入另一个文件，接着就完成了！</strong></p>
<p>However, things become complicated when we look more closely and memory is taken into account.</p>
<p>然而，当我们仔细观察并将内存考虑在内时，事情就变得复杂了。</p>
<p>As depicted in the dataflow below, the file read from disk must go through kernel system cache — which resides in the kernel space, then the data is copied to userspace’s memory area before being written back to a new file — which then in turn goes to kernel memory buffer before really flushed out to disk. </p>
<p>如下面的数据流所示，从磁盘读取的文件必须经过内核系统缓存（位于内核空间），然后数据被复制到用户空间的内存区域，再写回一个新文件，然后再进入内核内存缓冲区，最后被刷新到磁盘。</p>
<p>The procedure takes quite many unnecessary operations of copying back and forth between kernel and userspace without actually doing anything, and the operations consume system resources and context switches as well. </p>
<p>这个过程需要在内核和用户空间之间进行大量不必要的来回复制操作，但实际上什么都没做，而且这些操作还会消耗系统资源和上下文切换。</p>
<p>There’re room for improvement.</p>
<p>当然这部分还有改进余地。</p>
<a id="more"></a>

<p>Zero-copy technique comes into play with the purpose of eliminating all the unnecessary copies. In the Linux world the system call for that kind of work is <strong><em>sendfile().</em></strong></p>
<p>零拷贝技术的目的是<strong>消除所有不必要的拷贝</strong>。在 Linux 世界中，这种工作的系统调用是 **_sendfile()。</p>
<p><img src="https://adong-picture.oss-cn-shenzhen.aliyuncs.com/adong/20230825130421.png" alt="image.png"></p>
<p>Differences between data transfer using read()+write() / sendfile()</p>
<p>使用 <code>read()+write() / sendfile()</code> 进行数据传输的区别</p>
<h1 id="What-is-Zero-copy"><a href="#What-is-Zero-copy" class="headerlink" title="What is Zero-copy"></a>What is Zero-copy</h1><p><em>sendfile()</em> claims to make data transfer happening under kernel space only — i.e data transferred from kernel system cache to NIC buffer (or traversed through kernel system cache if local copy), thus doesnt require context switches as in read+write combination. </p>
<p><em>sendfile()</em> 声称只在内核空间进行数据传输，即数据从内核系统缓存传输到网卡缓冲区（如果是本地拷贝，则穿过内核系统缓存），因此不需要像读写结合那样进行上下文切换。</p>
<p><em>sendfile()</em> has now been widely used as a supported data transfering technique especially under <strong><em>nginx</em></strong> <em>and</em> <strong><em>kafka.</em></strong></p>
<p>现在，<em>sendfile()</em> 已被广泛用作一种受支持的数据传输技术，尤其是在<strong><em>nginx</em></strong> _和**_kafka下。</p>
<p>For ease of understanding we demonstrate a simple local file copy rather than file transfer over networking, and all the code’s error checking procedures are left out for clarity as well.</p>
<p>为了便于理解，我们演示的是简单的本地文件复制，而不是通过网络进行文件传输，而且为了清楚起见，我们也省略了代码中所有的错误检查程序。</p>
<p><strong><em>readwrite.c</em></strong></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;  </span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/types.h&gt;  </span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/stat.h&gt;  </span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;fcntl.h&gt;#define BUF_SIZE 4096*1000</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> **argv)</span> </span>&#123;  </span><br><span class="line">    <span class="keyword">char</span> buf[BUF_SIZE];  </span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">char</span> *fromfile = argv[<span class="number">1</span>];  </span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">char</span> *tofile = argv[<span class="number">2</span>];  </span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">stat</span> <span class="title">stat_buf</span>;</span>  </span><br><span class="line">    <span class="keyword">int</span> fromfd = <span class="built_in">open</span>(fromfile, O_RDONLY);  </span><br><span class="line">    fstat(fromfd, &amp;stat_buf);  </span><br><span class="line">    <span class="keyword">int</span> tofd = <span class="built_in">open</span>(tofile, O_WRONLY | O_CREAT, stat_buf.st_mode);    <span class="keyword">int</span> n;  </span><br><span class="line">    <span class="keyword">while</span> ((n = <span class="built_in">read</span>(fromfd, &amp;buf, <span class="keyword">sizeof</span>(buf))) &gt; <span class="number">0</span>) &#123;  </span><br><span class="line">        <span class="built_in">write</span>(tofd, &amp;buf, n);  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong><em>buf[BUF_SIZE]</em></strong> is the <em>user-space buffer</em> that we’re talking about, as can be seen for every iteration, <em>read()</em> copies data from file (through system memory cache) to this buffer, and <em>write()</em> copies data from the buffer to another file (through system memory buffer)</p>
<p><strong><em>buf[BUF_SIZE]</em></strong> 就是我们所说的<strong>用户空间缓冲区</strong>，可以看到，每次迭代时，<em>read()</em> 都会将数据从文件（通过系统内存缓存）复制到该缓冲区，而 <em>write()</em> 则会将数据从缓冲区复制到另一个文件（通过系统内存缓冲区）。</p>
<p>In the process memory map, <em>buf[BUF_SIZE]</em> can be seen as a allocation of 4MB on stack area. Reducing the buffer size can help reduce the waste of memory, but it in turn increases number of read() and write() system calls, which is expensive as well.</p>
<p>在进程内存映射中，<em>buf[BUF_SIZE]</em> 可以看作是在堆栈区域分配的 4MB 内存。减小缓冲区大小有助于减少内存浪费，但这反过来又会增加 read() 和 write() 系统调用的次数，而且代价高昂。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">00007f53e08f6000       4       4       4 rw---   [ anon ]  </span><br><span class="line">00007fff5a6b1000    4012    4008    4008 rw---   [ stack ]  </span><br><span class="line">00007fff5ab3e000      12       0       0 r----   [ anon ]  </span><br><span class="line">00007fff5ab41000       8       4       0 r-x--   [ anon ]</span><br></pre></td></tr></table></figure>

<p>In the example, we demonstrate only one file transfer, for many transfers the memory waste might be significantly noticable using this naive technique.</p>
<p>在示例中，我们只演示了一次文件传输，而对于多次传输，使用这种简单的技术可能会造成明显的内存浪费。</p>
<p><strong><em>sendfile.c</em></strong></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/types.h&gt;  </span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/stat.h&gt;  </span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;fcntl.h&gt;  </span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/sendfile.h&gt;#define BUF_SIZE 4096*1000int main(int argc, char **argv) &#123;  </span></span></span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">char</span> *fromfile = argv[<span class="number">1</span>];  </span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">char</span> *tofile = argv[<span class="number">2</span>];  </span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">stat</span> <span class="title">stat_buf</span>;</span>  </span><br><span class="line">    <span class="keyword">int</span> fromfd = <span class="built_in">open</span>(fromfile, O_RDONLY);  </span><br><span class="line">    fstat(fromfd, &amp;stat_buf);  </span><br><span class="line">    <span class="keyword">int</span> tofd = <span class="built_in">open</span>(tofile, O_WRONLY | O_CREAT, stat_buf.st_mode);    <span class="keyword">int</span> n = <span class="number">1</span>;  </span><br><span class="line">    <span class="keyword">while</span> (n &gt; <span class="number">0</span>) &#123;  </span><br><span class="line">        n = sendfile(tofd, fromfd, <span class="number">0</span>, BUF_SIZE);  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>There’s no user-space buffer for <em>sendfile().</em> For that reason, sendfile can send all the data from file at once, which eliminates the need of BUF_SIZE and a while loop, however we still keep it for comparing with read/write technique.</p>
<p>因此，<code>sendfile</code> 可以一次性发送文件中的所有数据，这样就不需要 用户空间 BUF_SIZE 和 while 循环，但我们需要仍然保留它，以便与读/写技术进行比较。</p>
<h1 id="Performance-benchmark"><a href="#Performance-benchmark" class="headerlink" title="Performance benchmark"></a>Performance benchmark</h1><p>Copy of a ~1G file. BUF_SIZE = 4K.</p>
<p>案例，复制一个1G 文件。BUF_SIZE = 4K。</p>
<p><strong>readwrite</strong></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">syscall            calls    total       <span class="built_in">min</span>       avg       <span class="built_in">max</span>       </span><br><span class="line">                               (msec)    (msec)    (msec)    (msec)  </span><br><span class="line">   --------------- -------- --------- --------- --------- ---------   </span><br><span class="line">   <span class="built_in">read</span>              <span class="number">244797</span> <span class="number">16974.624</span>     <span class="number">0.002</span>     <span class="number">0.069</span>   <span class="number">457.333</span>  </span><br><span class="line">   <span class="built_in">write</span>             <span class="number">245169</span>  <span class="number">2182.295</span>     <span class="number">0.004</span>     <span class="number">0.009</span>   <span class="number">268.689</span></span><br></pre></td></tr></table></figure>

<p>number of read / write is nearly the same, read() takes significanly more time because of major page faults.</p>
<p>读/写次数几乎相同，但 <code>read()</code> 要花费更多时间，因为会出现大的页面故障。</p>
<p><strong>sendfile</strong></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">syscall            calls    total       <span class="built_in">min</span>       avg       <span class="built_in">max</span>     </span><br><span class="line">                               (msec)    (msec)    (msec)    (msec)     </span><br><span class="line">   --------------- -------- --------- --------- --------- ---------  </span><br><span class="line">   sendfile          <span class="number">245261</span> <span class="number">13559.231</span>     <span class="number">0.004</span>     <span class="number">0.055</span>   <span class="number">185.970</span></span><br></pre></td></tr></table></figure>

<p>number of sendfile() calls is by half of the total of read()+write(), which also helps reduce total execution time. For context switches, there’s lack of observation tool so it’s difficult to show the differences.</p>
<p><strong>sendfile()</strong> 调用次数是 <code>read()+write()</code> 调用次数的一半，这也有助于减少总执行时间。至于上下文切换，由于缺乏观察工具，很难显示出差异。</p>
<p>In conclusion, <em>sendfile()</em> brings to the table several benefits, including reduction of context switches, memory usage, number of system calls, and eventually faster operations. </p>
<p>总之，<em>sendfile()</em> 能带来多种好处，包括减少上下文切换、内存使用、系统调用次数，以及最终加快操作速度。</p>
<p>It is, however, not the silver bullet for everything, we once encountered the <span class="exturl" data-url="aHR0cHM6Ly90cmFjLm5naW54Lm9yZy9uZ2lueC90aWNrZXQvMTg3MA==" title="https://trac.nginx.org/nginx/ticket/1870">problem of large file download on nginx,<i class="fa fa-external-link"></i></span> therefore usage of <em>sendfile()</em> should be considered and tested carefully before production use.</p>
<p>然而，它并不是万能的，我们曾经遇到过<span class="exturl" data-url="aHR0cHM6Ly90cmFjLm5naW54Lm9yZy9uZ2lueC90aWNrZXQvMTg3MA==" title="https://trac.nginx.org/nginx/ticket/1870">nginx 上下载大文件的问题<i class="fa fa-external-link"></i></span>，因此在生产使用 <em>sendfile()</em> 之前，应仔细考虑和测试。</p>
<h1 id="References"><a href="#References" class="headerlink" title="References"></a>References</h1><ul>
<li>Chapter 61 — The Linux Programming Interface — Michael Kerrisk  </li>
<li>第 61 章 - Linux 编程接口 - Michael Kerrisk</li>
<li><span class="exturl" data-url="aHR0cHM6Ly9kZXZlbG9wZXIuaWJtLmNvbS9hcnRpY2xlcy9qLXplcm9jb3B5Lw==" title="https://developer.ibm.com/articles/j-zerocopy/">https://developer.ibm.com/articles/j-zerocopy/<i class="fa fa-external-link"></i></span></li>
<li><span class="exturl" data-url="aHR0cDovL25naW54Lm9yZy9lbi9kb2NzL2h0dHAvbmd4X2h0dHBfY29yZV9tb2R1bGUuaHRtbCNzZW5kZmlsZQ==" title="http://nginx.org/en/docs/http/ngx_http_core_module.html#sendfile">http://nginx.org/en/docs/http/ngx_http_core_module.html#sendfile<i class="fa fa-external-link"></i></span></li>
<li><span class="exturl" data-url="aHR0cHM6Ly9rYWZrYS5hcGFjaGUub3JnLzA4L2RvY3VtZW50YXRpb24uaHRtbA==" title="https://kafka.apache.org/08/documentation.html">https://kafka.apache.org/08/documentation.html<i class="fa fa-external-link"></i></span></li>
</ul>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/kity@2.0.4/dist/kity.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text/javascript" src="https://cdn.jsdelivr.net/npm/hexo-simple-mindmap@0.2.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/hexo-simple-mindmap@0.2.0/dist/mindmap.min.css">
    </div>

    
    
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>lazytime
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://whitestore.top/2023/09/13/zerocopy/" title="【Linux】Linux Zero-Copy Using sendfile">https://whitestore.top/2023/09/13/zerocopy/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <span class="exturl" data-url="aHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzQuMC96aC1DTg=="><i class="fa fa-fw fa-creative-commons"></i>BY-NC</span> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/Linux/" rel="tag"># Linux</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2023/09/13/passarguments/" rel="prev" title="【Linux】Pass arguments into a function">
      <i class="fa fa-chevron-left"></i> 【Linux】Pass arguments into a function
    </a></div>
      <div class="post-nav-item">
    <a href="/2023/10/21/worktimestampmysql/" rel="next" title="【Mysql】Working with time zones, timestamps and datetimes in Laravel and MySQL">
      【Mysql】Working with time zones, timestamps and datetimes in Laravel and MySQL <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          
    <div class="comments" id="valine-comments"></div>

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#Source"><span class="nav-number">1.</span> <span class="nav-text">Source</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Why-Zero-copy"><span class="nav-number">2.</span> <span class="nav-text">Why Zero-copy?</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#What-is-Zero-copy"><span class="nav-number">3.</span> <span class="nav-text">What is Zero-copy</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Performance-benchmark"><span class="nav-number">4.</span> <span class="nav-text">Performance benchmark</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#References"><span class="nav-number">5.</span> <span class="nav-text">References</span></a></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">阿东</p>
  <div class="site-description" itemprop="description">随遇而安</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">239</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">36</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">37</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2xhenlUaW1lcw==" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;lazyTimes"><i class="fa fa-fw fa-github"></i>GitHub</span>
      </span>
      <span class="links-of-author-item">
        <span class="exturl" data-url="bWFpbHRvOjEwOTc0ODM1MDhAcXEuY29t" title="E-Mail → mailto:1097483508@qq.com"><i class="fa fa-fw fa-envelope"></i>E-Mail</span>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title">
      <i class="fa fa-fw fa-link"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <span class="exturl" data-url="aHR0cHM6Ly93d3cuNTJwb2ppZS5jbi9ob21lLnBocD9tb2Q9c3BhY2UmdWlkPTE0OTc3MTgmZG89dGhyZWFkJnZpZXc9bWUmZnJvbT1zcGFjZQ==" title="https:&#x2F;&#x2F;www.52pojie.cn&#x2F;home.php?mod&#x3D;space&amp;uid&#x3D;1497718&amp;do&#x3D;thread&amp;view&#x3D;me&amp;from&#x3D;space">吾爱破解</span>
        </li>
        <li class="links-of-blogroll-item">
          <span class="exturl" data-url="aHR0cHM6Ly9qdWVqaW4uaW0vdXNlci8yOTk5MTIzNDUyNjI2MzY2" title="https:&#x2F;&#x2F;juejin.im&#x2F;user&#x2F;2999123452626366">掘金</span>
        </li>
        <li class="links-of-blogroll-item">
          <span class="exturl" data-url="aHR0cHM6Ly9zZWdtZW50ZmF1bHQuY29tL3UvbGF6eXRpbWVz" title="https:&#x2F;&#x2F;segmentfault.com&#x2F;u&#x2F;lazytimes">思否</span>
        </li>
    </ul>
  </div>

      </div>

      <div class="wechat_OA">
        <span>欢迎关注我的公众号</span>
        <br>
          <!-- 这里添加你的二维码图片 -->
        <img src ="https://adong-picture.oss-cn-shenzhen.aliyuncs.com/adong/wechat_channel.jpg">
      </div>
        <div class="back-to-top motion-element">
          <i class="fa fa-arrow-up"></i>
          <span>0%</span>
        </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">阿东</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
      <span class="post-meta-item-text">站点总字数：</span>
    <span title="站点总字数">2m</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
      <span class="post-meta-item-text">站点阅读时长 &asymp;</span>
    <span title="站点阅读时长">29:50</span>
</div>
  <div class="powered-by">由 <span class="exturl theme-link" data-url="aHR0cHM6Ly9oZXhvLmlv">Hexo</span> & <span class="exturl theme-link" data-url="aHR0cHM6Ly90aGVtZS1uZXh0Lm9yZw==">NexT.Gemini</span> 强力驱动
  </div>

        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script>
  <script src="//cdn.jsdelivr.net/gh/fancyapps/fancybox@3/dist/jquery.fancybox.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  




  
<script src="/js/local-search.js"></script>













  

  


<script>
NexT.utils.loadComments(document.querySelector('#valine-comments'), () => {
  NexT.utils.getScript('//unpkg.com/valine/dist/Valine.min.js', () => {
    var GUEST = ['nick', 'mail', 'link'];
    var guest = 'nick,mail,link';
    guest = guest.split(',').filter(item => {
      return GUEST.includes(item);
    });
    new Valine({
      el         : '#valine-comments',
      verify     : false,
      notify     : true,
      appId      : 'qMUpEEvBgXaMDD1b0ftgi9xr-gzGzoHsz',
      appKey     : 'UCdfT4Rfih6MO6y8DI4fstf6',
      placeholder: "Just go go",
      avatar     : 'mm',
      meta       : guest,
      pageSize   : '10' || 10,
      visitor    : false,
      lang       : 'zh-CN' || 'zh-cn',
      path       : location.pathname,
      recordIP   : false,
      serverURLs : ''
    });
  }, window.Valine);
});
</script>

</body>
</html>
